The state data set
Data wrangling
First take a look at the state data.
state.x77 <- data.frame(state.x77)
sta <- cbind(state.abb, state.x77, state.region) #combine the three data sets
colnames(sta)[1] <- "State" #Rename first column
colnames(sta)[10] <- "Region" #Rename the 10th column
sta$Pop.Density <- sta$Population/sta$Area
head(sta)
str(sta)
'data.frame': 50 obs. of 11 variables:
$ State : Factor w/ 50 levels "AK","AL","AR",..: 2 1 4 3 5 6 7 8 9 10 ...
$ Population : num 3615 365 2212 2110 21198 ...
$ Income : num 3624 6315 4530 3378 5114 ...
$ Illiteracy : num 2.1 1.5 1.8 1.9 1.1 0.7 1.1 0.9 1.3 2 ...
$ Life.Exp : num 69 69.3 70.5 70.7 71.7 ...
$ Murder : num 15.1 11.3 7.8 10.1 10.3 6.8 3.1 6.2 10.7 13.9 ...
$ HS.Grad : num 41.3 66.7 58.1 39.9 62.6 63.9 56 54.6 52.6 40.6 ...
$ Frost : num 20 152 15 65 20 166 139 103 11 60 ...
$ Area : num 50708 566432 113417 51945 156361 ...
$ Region : Factor w/ 4 levels "Northeast","South",..: 2 4 4 2 4 4 1 2 2 2 ...
$ Pop.Density: num 0.071291 0.000644 0.019503 0.04062 0.135571 ...
Scatter plot
Let’s start with this scatterplot. Try to run the first line but without the “+” at the end. Then gradually add one line at a time without the “+” at the end and see the effect. You can select the lines and then press Ctrl+Enter to run. Things are done in steps and layers in ggplot2. That’s where the “gg” comes from ( the Grammar of Graphics).
library(ggplot2)
ggplot(sta, aes(x = Illiteracy, y = Murder)) +
geom_point(aes(size = Pop.Density, color = Region)) +
geom_smooth(method = 'lm',formula = y ~ x) + # add regression line
theme(plot.title = element_text(hjust = 0.5)) +
ylim(c(0.5, 16)) +
xlim(c(0, 3)) +
ggtitle("Murder rate Vs Illiteracy") +
labs(y="Murders per 100,000", x="Illiteracy rate 1970", caption="Source: R") +
# guides(color=guide_legend("US Region"), size=guide_legend("Population Density")) +
guides(colour = guide_legend("US Region", order = 1), # change order
size = guide_legend("Pop. Density", order = 2)) +
theme(legend.position="bottom", legend.box = "horizontal") +
annotate("text", x= 2.5, y = 2, label = paste("R=",round(cor(sta$Murder, sta$Illiteracy), 2)),hjust= 3) +
geom_text(aes(label=State),hjust=0, vjust=0)

This kind of layout also makes it easy to comment out one line at a time to see the effect. This is done with the first guides verb. Each line starts with a verb that adds or customize something on the plot.
Challenge
Create a scatter plot to visualize the relationship between illiteracy rate and life expectancy. Color data points by region and vary the size of the data points according to income. Note: Start building step by step. Copy the copy from above line by line. Change xlim and ylim. Change axis labels. Change the Pearson’s correlation coefficient, and where it will appear on the plot using x, and y coordinates.
Lollipop plot
ggplot(sta, aes(x = State, y = Population)) +
geom_point( size=3, color="red", fill=alpha("orange", 0.3), alpha=0.5, shape=20, stroke=2) +
geom_segment(aes(x = State, xend = State, y = 0, yend = Population)) +
labs(title = "Lollipop Chart for Population") +
# coord_flip() +
theme( plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5))

Challenge
Try to see what happens by uncommenting the coord_flip line. And then create a lollipop plot for Frost (the number of days).
Density plot with ridgeline
# install.packages("ggridges")
library(ggridges)
ggplot(sta, aes(x = Murder, y = Region, fill = Region)) +
geom_density_ridges() +
theme_ridges() +
theme(legend.position = "none", plot.title = element_text(hjust = 0.5),
axis.title.x = element_text(hjust = 0.5), axis.title.y = element_text(hjust = 0.5))

Notice that the last line is split into 3 lines, all indended nicely.
Challenge
Use ridgeline plot to explore the regional distribution of Illiteracy for state.x77 and state.region data sets and interpret your figure.
Boxplot with jitter shows the raw data points
library(ggplot2)
ggplot(sta, aes(x = Region, y = Frost)) +
geom_boxplot()+
geom_jitter(position=position_jitter(0.2))

Challenge
Change it to visualize income. Fill the plain boxplots with 4 different colors for the 4 boxes.
st <- sta[, 2:9] #take numeric variables as goal matrix
# install.packages( c("ellipse", "corrplot") )
library(ellipse)
Attaching package: 㤼㸱ellipse㤼㸲
The following object is masked from 㤼㸱package:graphics㤼㸲:
pairs
library(corrplot)
corrplot 0.84 loaded
corMatrix <- cor(as.matrix(st)) # Calculate correlation matrix
col <- colorRampPalette(c("red", "yellow", "blue")) #Color values. Red, yellow and blue represent that the coefficients are -1, 0 and 1 respectively. You can use more than 3 colors to represent the coefficients ranging from -1 to 1.
corrplot.mixed(corMatrix, order = "AOE", lower = "number", lower.col = "black",
number.cex = .8, upper = "ellipse", upper.col = col(10),
diag = "u", tl.pos = "lt", tl.col = "black") #Type ?corrplot.mixed in the Console to get help in detail.

plot(hclust(as.dist(1 - cor(as.matrix(st))))) # hierarchical clustering

Heat maps made easy with ComplexHeatmap
library(ComplexHeatmap)
st.matrix <- as.matrix(st) # transfer the data frame to matrix
st.matrix <- apply(st.matrix, 2, function(y)(y - mean(y)) / sd(y)) # standardize data
row_ha = rowAnnotation( Region = sta$Region)
Heatmap(st.matrix, left_annotation = row_ha)

library(ComplexHeatmap)
st.matrix <- as.matrix(st) # transfer the data frame to matrix
st.matrix <- apply(st.matrix, 2, function(y)(y - mean(y)) / sd(y)) # standardize data
row_ha <- rowAnnotation( Region = sta$Region, Murder = anno_barplot(sta$Murder))
col_ha <- HeatmapAnnotation(Random = runif(8), foo = anno_density(st.matrix))
Heatmap(st.matrix,
left_annotation = row_ha,
top_annotation = col_ha)

Challenge
Add a annotation to the right of the heat map. Using points to represents income for 50 states. Hint: Make another column annotation function and then use right_annotation
Maps are also easy
#install.packages(c("maps","mapproj"))
library(ggplot2)
library(maps)
sta$region <- tolower(state.name) # Create new character vector with lowercase states names
states <- map_data("state") # Extract state data
map <- merge(states, sta, by = "region", all.x = T) # Merge states and state.x77 data
map <- map[order(map$order), ]
ggplot(map, aes(x = long, y = lat, group = group)) +
geom_polygon(aes(fill = Murder)) +
geom_path() +
scale_fill_gradientn(colours = rev(heat.colors(10))) +
coord_map() +
labs(x = "Longitude", y = "Latitude") +
guides(fill = guide_legend(title = "Murder Rate")) +
theme(plot.title = element_text(hjust = 0.5))

Challenge
Similar to above, create a new code chuck below to use choropleth map to obtain the Illiteracy map in state.x77 data set and give a brief interpretation. Hint: You can combine state.abb to state.x77 or use the row names of state.x77 data set directly.
Interactive plots with plotly
library(plotly)
p <- ggplot(sta, aes(x = Illiteracy, y = Murder)) +
geom_point(aes(color = Region)) +
theme(plot.title = element_text(hjust = 0.5)) +
ggtitle("Murder rate Vs Illiteracy") +
labs(y="Murders per 100,000", x="Illiteracy rate 1970", caption="Source: R") +
annotate("text", x= 2.5, y = 2,
label = paste("R=",round(cor(sta$Murder, sta$Illiteracy), 2)))
ggplotly(p)
LS0tDQp0aXRsZTogIkRhdGEgdmlzdWFsaXphdGlvbiB3aXRoIFIiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCi0tLQ0KIyBHZXQgcmVhZHkNCmBgYHtyIGV2YWw9RkFMU0V9DQojTWFrZSBzdXJlIHlvdSBoYXZlIGEgcmVjZW50IHZlcnNpb24gb2YgUiBhbmQgUnN0dWRpbw0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCmluc3RhbGwucGFja2FnZXMoYygicGxvdGx5IiwgInNoaW55IiwgInNoaW55QlMiKSkNCmluc3RhbGwucGFja2FnZXMoImdnZm9ydGlmeSIpDQppbnN0YWxsLnBhY2thZ2VzKCJEYXRhRXhwbG9yZXIiKQ0KaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCmluc3RhbGwucGFja2FnZXMoYygiVmVubkRpYWdyYW0iLCJVcFNldFIiKSApDQppbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKQ0KaW5zdGFsbC5wYWNrYWdlcygidmlzTmV0d29yayIpDQppbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpDQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQ29tcGxleEhlYXRtYXAiKSANCmluc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKQ0KYGBgDQoNCg0KIyBZZXMsIEkgY2FuIGRvIGl0IQ0KKiBNYWtlIGl0IHNpbXBsZQ0KKiBObyBtb3JlIHRoYW4gNiB0eXBlcyBsaW5lcyBvciBtYXJrZXJzDQoqIFNvbWUgcGVvcGxlIGFyZSBjb2xvciBibGluZA0KKiBEbyBleHBsb3JhdG9yeSBwbG90cyBmYXN0IHdpdGggZGVmYXVsdCBzZXR0aW5ncw0KKiBGaW5lIHR1bmUgc2VsZWN0ZWQga2V5IHBsb3RzIGZvciBwcmVzZW50YXRpb24NCiogVXNlIHRpZHl2ZXJzZSBhbmQgc3RhcnQgdGlkeWluZw0KKiBUaGVyZSBpcyBhbiBSIHBhY2thZ2UgZm9yIGV2ZXJ5dGhpbmchDQoqIERvbid0IG1ha2UgbWUgdGhpbmshDQoNCg0KIyBUaGUgc3RhdGUgZGF0YSBzZXQNCiMjIERhdGEgd3JhbmdsaW5nDQpGaXJzdCB0YWtlIGEgbG9vayBhdCB0aGUgc3RhdGUgZGF0YS4NCg0KYGBge3J9DQpzdGF0ZS54NzcgPC0gZGF0YS5mcmFtZShzdGF0ZS54NzcpICAgDQpzdGEgPC0gY2JpbmQoc3RhdGUuYWJiLCBzdGF0ZS54NzcsIHN0YXRlLnJlZ2lvbikgI2NvbWJpbmUgdGhlIHRocmVlIGRhdGEgc2V0cw0KY29sbmFtZXMoc3RhKVsxXSA8LSAiU3RhdGUiICAgICAgICAgICAgICAgICNSZW5hbWUgZmlyc3QgY29sdW1uDQpjb2xuYW1lcyhzdGEpWzEwXSA8LSAiUmVnaW9uIiAgICAgICAgICAgICAgI1JlbmFtZSB0aGUgMTB0aCBjb2x1bW4NCnN0YSRQb3AuRGVuc2l0eSA8LSBzdGEkUG9wdWxhdGlvbi9zdGEkQXJlYQ0KaGVhZChzdGEpIA0KYGBgDQoNCmBgYHtyfQ0Kc3RyKHN0YSkNCmBgYA0KDQojIyBTY2F0dGVyIHBsb3QNCkxldCdzIHN0YXJ0IHdpdGggdGhpcyBzY2F0dGVycGxvdC4gVHJ5IHRvIHJ1biB0aGUgZmlyc3QgbGluZSBidXQgd2l0aG91dCB0aGUgIisiIGF0IHRoZSBlbmQuIFRoZW4gZ3JhZHVhbGx5IGFkZCBvbmUgbGluZSBhdCBhIHRpbWUgd2l0aG91dCB0aGUgIisiIGF0IHRoZSBlbmQgYW5kIHNlZSB0aGUgZWZmZWN0LiBZb3UgY2FuIHNlbGVjdCB0aGUgbGluZXMgYW5kIHRoZW4gcHJlc3MgQ3RybCtFbnRlciB0byBydW4uIFRoaW5ncyBhcmUgZG9uZSBpbiBzdGVwcyBhbmQgbGF5ZXJzIGluIGdncGxvdDIuIFRoYXQncyB3aGVyZSB0aGUgImdnIiBjb21lcyBmcm9tICggdGhlIEdyYW1tYXIgb2YgR3JhcGhpY3MpLiANCmBgYHtyLCBmaWcuaGVpZ2h0ID0gNiwgZmlnLndpZHRoID0gNiwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpsaWJyYXJ5KGdncGxvdDIpDQpnZ3Bsb3Qoc3RhLCBhZXMoeCA9IElsbGl0ZXJhY3ksIHkgPSBNdXJkZXIpKSArIA0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gUG9wLkRlbnNpdHksIGNvbG9yID0gUmVnaW9uKSkgKyANCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJyxmb3JtdWxhID0geSB+IHgpICsgICMgYWRkIHJlZ3Jlc3Npb24gbGluZQ0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICB5bGltKGMoMC41LCAxNikpICsNCiAgeGxpbShjKDAsIDMpKSArDQogIGdndGl0bGUoIk11cmRlciByYXRlIFZzIElsbGl0ZXJhY3kiKSArDQogIGxhYnMoeT0iTXVyZGVycyBwZXIgMTAwLDAwMCIsIHg9IklsbGl0ZXJhY3kgcmF0ZSAxOTcwIiwgY2FwdGlvbj0iU291cmNlOiBSIikgKw0KICAjIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIlVTIFJlZ2lvbiIpLCBzaXplPWd1aWRlX2xlZ2VuZCgiUG9wdWxhdGlvbiBEZW5zaXR5IikpICsNCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZCgiVVMgUmVnaW9uIiwgb3JkZXIgPSAxKSwgIyBjaGFuZ2Ugb3JkZXINCiAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQoIlBvcC4gRGVuc2l0eSIsIG9yZGVyID0gMikpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgKyANCiAgYW5ub3RhdGUoInRleHQiLCAgeD0gMi41LCB5ID0gMiwgbGFiZWwgPSBwYXN0ZSgiUj0iLHJvdW5kKGNvcihzdGEkTXVyZGVyLCBzdGEkSWxsaXRlcmFjeSksIDIpKSxoanVzdD0gMykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPVN0YXRlKSxoanVzdD0wLCB2anVzdD0wKQ0KDQpgYGANCg0KVGhpcyBraW5kIG9mIGxheW91dCBhbHNvIG1ha2VzIGl0IGVhc3kgdG8gY29tbWVudCBvdXQgb25lIGxpbmUgYXQgYSB0aW1lIHRvIHNlZSB0aGUgZWZmZWN0LiBUaGlzIGlzIGRvbmUgd2l0aCB0aGUgZmlyc3QgKipndWlkZXMqKiB2ZXJiLiBFYWNoIGxpbmUgc3RhcnRzIHdpdGggYSB2ZXJiIHRoYXQgYWRkcyBvciBjdXN0b21pemUgc29tZXRoaW5nIG9uIHRoZSBwbG90LiANCg0KKipDaGFsbGVuZ2UqKiAgDQoNCj4gQ3JlYXRlIGEgc2NhdHRlciBwbG90IHRvIHZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gaWxsaXRlcmFjeSByYXRlIGFuZCBsaWZlIGV4cGVjdGFuY3kuIENvbG9yIGRhdGEgcG9pbnRzIGJ5IHJlZ2lvbiBhbmQgdmFyeSB0aGUgc2l6ZSBvZiB0aGUgZGF0YSBwb2ludHMgYWNjb3JkaW5nIHRvIGluY29tZS4gICBOb3RlOiBTdGFydCBidWlsZGluZyBzdGVwIGJ5IHN0ZXAuIENvcHkgdGhlIGNvcHkgZnJvbSBhYm92ZSBsaW5lIGJ5IGxpbmUuIENoYW5nZSB4bGltIGFuZCB5bGltLiBDaGFuZ2UgYXhpcyBsYWJlbHMuIENoYW5nZSB0aGUgUGVhcnNvbidzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50LCBhbmQgd2hlcmUgaXQgd2lsbCBhcHBlYXIgb24gdGhlIHBsb3QgdXNpbmcgeCwgYW5kIHkgY29vcmRpbmF0ZXMuIA0KDQoNCiMjIExvbGxpcG9wIHBsb3QNCmBgYHtyLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gN30NCmdncGxvdChzdGEsIGFlcyh4ID0gU3RhdGUsIHkgPSBQb3B1bGF0aW9uKSkgKw0KICBnZW9tX3BvaW50KCBzaXplPTMsIGNvbG9yPSJyZWQiLCBmaWxsPWFscGhhKCJvcmFuZ2UiLCAwLjMpLCBhbHBoYT0wLjUsIHNoYXBlPTIwLCBzdHJva2U9MikgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSBTdGF0ZSwgeGVuZCA9IFN0YXRlLCB5ID0gMCwgeWVuZCA9IFBvcHVsYXRpb24pKSArDQogIGxhYnModGl0bGUgPSAiTG9sbGlwb3AgQ2hhcnQgZm9yIFBvcHVsYXRpb24iKSArDQojICBjb29yZF9mbGlwKCkgICsgDQogIHRoZW1lKCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKSANCmBgYA0KDQoqKkNoYWxsZW5nZSoqDQoNCj4gVHJ5IHRvIHNlZSB3aGF0IGhhcHBlbnMgYnkgdW5jb21tZW50aW5nIHRoZSBjb29yZF9mbGlwIGxpbmUuIEFuZCB0aGVuIGNyZWF0ZSBhIGxvbGxpcG9wIHBsb3QgZm9yIEZyb3N0ICh0aGUgbnVtYmVyIG9mIGRheXMpLg0KDQoNCiMjIERlbnNpdHkgcGxvdCB3aXRoIHJpZGdlbGluZQ0KYGBge3J9DQojIGluc3RhbGwucGFja2FnZXMoImdncmlkZ2VzIikNCmxpYnJhcnkoZ2dyaWRnZXMpDQpnZ3Bsb3Qoc3RhLCBhZXMoeCA9IE11cmRlciwgeSA9IFJlZ2lvbiwgZmlsbCA9IFJlZ2lvbikpICsNCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcygpICsNCiAgdGhlbWVfcmlkZ2VzKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCANCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoNCk5vdGljZSB0aGF0IHRoZSBsYXN0IGxpbmUgaXMgc3BsaXQgaW50byAzIGxpbmVzLCBhbGwgaW5kZW5kZWQgbmljZWx5LiANCg0KKipDaGFsbGVuZ2UqKiANCg0KPiBVc2UgcmlkZ2VsaW5lIHBsb3QgdG8gZXhwbG9yZSB0aGUgcmVnaW9uYWwgZGlzdHJpYnV0aW9uIG9mIElsbGl0ZXJhY3kgZm9yIHN0YXRlLng3NyBhbmQgc3RhdGUucmVnaW9uIGRhdGEgc2V0cyBhbmQgaW50ZXJwcmV0IHlvdXIgZmlndXJlLg0KDQojIyBCb3hwbG90IHdpdGggaml0dGVyIHNob3dzIHRoZSByYXcgZGF0YSBwb2ludHMNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KHN0YSwgYWVzKHggPSBSZWdpb24sIHkgPSBGcm9zdCkpICsgDQogIGdlb21fYm94cGxvdCgpKw0KICBnZW9tX2ppdHRlcihwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIoMC4yKSkNCmBgYA0KKipDaGFsbGVuZ2UqKg0KDQo+ICBDaGFuZ2UgaXQgdG8gdmlzdWFsaXplIGluY29tZS4gRmlsbCB0aGUgcGxhaW4gYm94cGxvdHMgd2l0aCA0IGRpZmZlcmVudCBjb2xvcnMgZm9yIHRoZSA0IGJveGVzLg0KDQoNCmBgYHtyfQ0Kc3QgPC0gc3RhWywgMjo5XSAjdGFrZSBudW1lcmljIHZhcmlhYmxlcyBhcyBnb2FsIG1hdHJpeA0KIyBpbnN0YWxsLnBhY2thZ2VzKCBjKCJlbGxpcHNlIiwgImNvcnJwbG90IikgKQ0KbGlicmFyeShlbGxpcHNlKQ0KbGlicmFyeShjb3JycGxvdCkNCmNvck1hdHJpeCA8LSBjb3IoYXMubWF0cml4KHN0KSkgIyBDYWxjdWxhdGUgY29ycmVsYXRpb24gbWF0cml4DQpjb2wgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJyZWQiLCAieWVsbG93IiwgImJsdWUiKSkgICAjQ29sb3IgdmFsdWVzLiBSZWQsIHllbGxvdyBhbmQgYmx1ZSByZXByZXNlbnQgdGhhdCB0aGUgY29lZmZpY2llbnRzIGFyZSAtMSwgMCBhbmQgMSByZXNwZWN0aXZlbHkuIFlvdSBjYW4gdXNlIG1vcmUgdGhhbiAzIGNvbG9ycyB0byByZXByZXNlbnQgdGhlIGNvZWZmaWNpZW50cyByYW5naW5nIGZyb20gLTEgdG8gMS4NCmNvcnJwbG90Lm1peGVkKGNvck1hdHJpeCwgb3JkZXIgPSAiQU9FIiwgbG93ZXIgPSAibnVtYmVyIiwgbG93ZXIuY29sID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBudW1iZXIuY2V4ID0gLjgsIHVwcGVyID0gImVsbGlwc2UiLCAgdXBwZXIuY29sID0gY29sKDEwKSwgDQogICAgICAgICAgICAgICBkaWFnID0gInUiLCB0bC5wb3MgPSAibHQiLCB0bC5jb2wgPSAiYmxhY2siKSAjVHlwZSA/Y29ycnBsb3QubWl4ZWQgaW4gdGhlIENvbnNvbGUgdG8gZ2V0IGhlbHAgaW4gZGV0YWlsLg0KYGBgDQoNCmBgYHtyfQ0KcGxvdChoY2x1c3QoYXMuZGlzdCgxIC0gY29yKGFzLm1hdHJpeChzdCkpKSkpICAjIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nDQpgYGANCg0KDQojIyBIZWF0IG1hcHMgbWFkZSBlYXN5IHdpdGggQ29tcGxleEhlYXRtYXANCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDZ9DQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQ0Kc3QubWF0cml4IDwtIGFzLm1hdHJpeChzdCkgIyB0cmFuc2ZlciB0aGUgZGF0YSBmcmFtZSB0byBtYXRyaXgNCnN0Lm1hdHJpeCA8LSBhcHBseShzdC5tYXRyaXgsIDIsIGZ1bmN0aW9uKHkpKHkgLSBtZWFuKHkpKSAvIHNkKHkpKSAgIyBzdGFuZGFyZGl6ZSBkYXRhDQpyb3dfaGEgPSByb3dBbm5vdGF0aW9uKCBSZWdpb24gPSBzdGEkUmVnaW9uKQ0KSGVhdG1hcChzdC5tYXRyaXgsIGxlZnRfYW5ub3RhdGlvbiA9IHJvd19oYSkNCmBgYA0KYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gOH0NCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApDQpzdC5tYXRyaXggPC0gYXMubWF0cml4KHN0KSAjIHRyYW5zZmVyIHRoZSBkYXRhIGZyYW1lIHRvIG1hdHJpeA0Kc3QubWF0cml4IDwtIGFwcGx5KHN0Lm1hdHJpeCwgMiwgZnVuY3Rpb24oeSkoeSAtIG1lYW4oeSkpIC8gc2QoeSkpICAjIHN0YW5kYXJkaXplIGRhdGENCnJvd19oYSA8LSByb3dBbm5vdGF0aW9uKCBSZWdpb24gPSBzdGEkUmVnaW9uLCBNdXJkZXIgPSBhbm5vX2JhcnBsb3Qoc3RhJE11cmRlcikpDQpjb2xfaGEgPC0gSGVhdG1hcEFubm90YXRpb24oUmFuZG9tID0gcnVuaWYoOCksIGZvbyA9IGFubm9fZGVuc2l0eShzdC5tYXRyaXgpKQ0KSGVhdG1hcChzdC5tYXRyaXgsIA0KICAgICAgICBsZWZ0X2Fubm90YXRpb24gPSByb3dfaGEsIA0KICAgICAgICB0b3BfYW5ub3RhdGlvbiA9IGNvbF9oYSkNCmBgYA0KDQoqKkNoYWxsZW5nZSoqDQoNCj4gQWRkIGEgYW5ub3RhdGlvbiB0byB0aGUgcmlnaHQgb2YgdGhlIGhlYXQgbWFwLiBVc2luZyBwb2ludHMgdG8gcmVwcmVzZW50cyBpbmNvbWUgZm9yIDUwIHN0YXRlcy4gSGludDogTWFrZSBhbm90aGVyIGNvbHVtbiBhbm5vdGF0aW9uIGZ1bmN0aW9uIGFuZCB0aGVuIHVzZSByaWdodF9hbm5vdGF0aW9uDQoNCg0KDQojIyBNYXBzIGFyZSBhbHNvIGVhc3kNCg0KYGBge3IgfQ0KI2luc3RhbGwucGFja2FnZXMoYygibWFwcyIsIm1hcHByb2oiKSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFwcykNCnN0YSRyZWdpb24gPC0gdG9sb3dlcihzdGF0ZS5uYW1lKSAgIyBDcmVhdGUgbmV3IGNoYXJhY3RlciB2ZWN0b3Igd2l0aCBsb3dlcmNhc2Ugc3RhdGVzIG5hbWVzDQpzdGF0ZXMgPC0gbWFwX2RhdGEoInN0YXRlIikgICAgICAgICMgRXh0cmFjdCBzdGF0ZSBkYXRhDQptYXAgPC0gbWVyZ2Uoc3RhdGVzLCBzdGEsIGJ5ID0gInJlZ2lvbiIsIGFsbC54ID0gVCkgICMgTWVyZ2Ugc3RhdGVzIGFuZCBzdGF0ZS54NzcgZGF0YQ0KbWFwIDwtIG1hcFtvcmRlcihtYXAkb3JkZXIpLCBdDQpnZ3Bsb3QobWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApKSArICANCiAgZ2VvbV9wb2x5Z29uKGFlcyhmaWxsID0gTXVyZGVyKSkgKyAgIA0KICBnZW9tX3BhdGgoKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzID0gcmV2KGhlYXQuY29sb3JzKDEwKSkpICsNCiAgY29vcmRfbWFwKCkgKw0KICBsYWJzKHggPSAiTG9uZ2l0dWRlIiwgeSA9ICJMYXRpdHVkZSIpICsNCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiTXVyZGVyIFJhdGUiKSkgKyAgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KYGBgDQoNCioqQ2hhbGxlbmdlKioNCg0KPiBTaW1pbGFyIHRvIGFib3ZlLCBjcmVhdGUgYSBuZXcgY29kZSBjaHVjayBiZWxvdyB0byB1c2UgY2hvcm9wbGV0aCBtYXAgdG8gb2J0YWluIHRoZSBJbGxpdGVyYWN5IG1hcCBpbiBzdGF0ZS54NzcgZGF0YSBzZXQgYW5kIGdpdmUgYSBicmllZiBpbnRlcnByZXRhdGlvbi4gSGludDogWW91IGNhbiBjb21iaW5lIHN0YXRlLmFiYiB0byBzdGF0ZS54Nzcgb3IgdXNlIHRoZSByb3cgbmFtZXMgb2Ygc3RhdGUueDc3IGRhdGEgc2V0IGRpcmVjdGx5LiANCg0KIyMgSW50ZXJhY3RpdmUgcGxvdHMgd2l0aCBwbG90bHkgDQoNCmBgYHtyfQ0KbGlicmFyeShwbG90bHkpDQpwIDwtIGdncGxvdChzdGEsIGFlcyh4ID0gSWxsaXRlcmFjeSwgeSA9IE11cmRlcikpICsgDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUmVnaW9uKSkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgZ2d0aXRsZSgiTXVyZGVyIHJhdGUgVnMgSWxsaXRlcmFjeSIpICsNCiAgbGFicyh5PSJNdXJkZXJzIHBlciAxMDAsMDAwIiwgeD0iSWxsaXRlcmFjeSByYXRlIDE5NzAiLCBjYXB0aW9uPSJTb3VyY2U6IFIiKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgIHg9IDIuNSwgeSA9IDIsIA0KICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJSPSIscm91bmQoY29yKHN0YSRNdXJkZXIsIHN0YSRJbGxpdGVyYWN5KSwgMikpKSANCg0KZ2dwbG90bHkocCwgKQ0KYGBgDQoNCg==